package com.zuijin.vue2blog.config;

import com.zuijin.vue2blog.component.JwtAuthenticationTokenFilter;
import com.zuijin.vue2blog.service.UserComDetailsService;
import com.zuijin.vue2blog.service.UserComService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/**
 * ClassName:    SecurityConfig
 * CreateBy:     IntelliJ IDEA
 * Author:       醉瑾
 * Date:         2022-04-20
 * Description :
 */
@Configuration
@EnableWebSecurity // 用于启用Web安全的注解 https://blog.csdn.net/andy_zhang2007/article/details/90023901
// @EnableGlobalMethodSecurity(prePostEnabled = true) // 曾经报错
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Lazy  // 解决循环依赖问题
    @Resource
    UserComService userComService;

    @Resource
    UserComDetailsService userComDetailsService;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable() // 使用 JWT，禁用csrf
                .sessionManagement() // 基于 token，不需要 session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);


        // 静态资源放行得两种方式 https://segmentfault.com/a/1190000022767227
        http.authorizeRequests()
                .antMatchers(HttpMethod.GET,
                        "/*.html", // 允许 Swagger 访问
                        "/favicon.ico",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/swagger-resources/**",
                        "/v3/**",
                        "/swagger-ui/**",
                        "/webjars/**",
                        "/doc.html").permitAll()
                .antMatchers("/user/com/login", "/user/com/register").permitAll() // 对登录注册允许匿名访问
                .antMatchers(HttpMethod.OPTIONS).permitAll() // 放行预检请求
                .anyRequest().authenticated(); // 除此之外都需要 鉴权认证

        // 禁用 header 缓存 https://www.jianshu.com/p/b8979141c2dd
        http.headers().cacheControl();

        // 添加 JWT filter
        http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userComDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
        return new JwtAuthenticationTokenFilter();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

//    // 重写 userDetailsService
//    @Override
//    protected UserDetailsService userDetailsService() {
//        // 获取登录用户信息
//        return username -> userComService.loadUserByUsername(username);
//    }
}
